namespace fctr {

#define n BOOST_PP_ITERATION()
#define PARAM_print(z, n, data) BOOST_PP_CAT(P,n) BOOST_PP_CAT(param,n);
#define PARSE_PARAM_print(z, n, data) BOOST_PP_CAT(param,n) = Convert<BOOST_PP_CAT(P,n)>::parse(data[n]);
#define ARCHIVE_PARAM_print(z, n, data) data & BOOST_SERIALIZATION_NVP(BOOST_PP_CAT(param,n));
#define ARG_PARAM_print(z, n, data) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(P,n) BOOST_PP_CAT(_param,n)
#define INIT_PARAM_print(z, n, data) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(param,n)(BOOST_PP_CAT(_param,n))

#if n
template<BOOST_PP_ENUM_PARAMS(n, class P)>
class BOOST_PP_CAT(Param,n)
: public Params 
{ 
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int file_version){
        // method 2 : explicitly register base/derived relationship
        boost::serialization::void_cast_register<BOOST_PP_CAT(Param,n), Params>(
            static_cast<BOOST_PP_CAT(Param,n) *>(NULL),
			static_cast<Params *>(NULL) 
        );
		BOOST_PP_REPEAT(n, ARCHIVE_PARAM_print, ar)
    }
public:
	BOOST_PP_REPEAT(n, PARAM_print, ~)
	// constructeur
	// constructeur
	BOOST_PP_CAT(Param,n)()
	{}
	BOOST_PP_CAT(Param,n)(BOOST_PP_REPEAT(n, ARG_PARAM_print, ~))
	:BOOST_PP_REPEAT(n, INIT_PARAM_print, ~)
	{}
	void parse(vector<string> & parameters){
		if (parameters.size() < n) 
			throw ParamOutOfBoundException(BOOST_PP_STRINGIZE(parameters must contain at least n arguments));
		BOOST_PP_REPEAT(n, PARSE_PARAM_print, parameters)
	}
};
#endif

#  undef ARG_PARAM_print
#  undef INIT_PARAM_print
#  undef ARCHIVE_PARAM_print
#  undef PARSE_PARAM_print
#  undef PARAM_print
#  undef n

}
